package io.github.junxworks.qt.modules.tushare.service.impl;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import io.github.junxworks.junx.core.util.DateUtils;
import io.github.junxworks.junx.core.util.StringUtils;
import io.github.junxworks.qt.modules.data.service.DataStoreService;
import io.github.junxworks.qt.modules.tushare.Fields;
import io.github.junxworks.qt.modules.tushare.TushareAPIs;
import io.github.junxworks.qt.modules.tushare.TushareConstants;
import io.github.junxworks.qt.modules.tushare.entity.DStockBlockTrade;
import io.github.junxworks.qt.modules.tushare.entity.DStockMoneyflow;
import io.github.junxworks.qt.modules.tushare.entity.DStockMoneyflowHsgt;
import io.github.junxworks.qt.modules.tushare.entity.DStockTradeCal;
import io.github.junxworks.qt.modules.tushare.entity.DStockTradeDaily;
import io.github.junxworks.qt.modules.tushare.entity.DStockTradeDailyBasic;
import io.github.junxworks.qt.modules.tushare.entity.DStockTradeMonthly;
import io.github.junxworks.qt.modules.tushare.entity.DStockTradeWeekly;
import io.github.junxworks.qt.modules.tushare.mapper.TradeInfoMapper;
import io.github.junxworks.qt.modules.tushare.service.TradeInfoService;
import io.github.junxworks.qt.modules.tushare.service.TushareService;

@Service("TushareTradeInfoService")
public class TushareTradeInfoService extends TushareService {

	@Autowired
	private TradeInfoMapper tradeInfoMapper;

	/** The data store service. */
	@Autowired
	private DataStoreService dataStoreService;

	@Autowired
	private TradeInfoService tradeInfoService;

	public void fetchTradeCal(String dateRange) {
		String begin = DateUtils.format(DateUtils.addDays(new Date(), -1), TushareConstants.TUSHARE_DATE_FORMAT);
		String end = DateUtils.format(new Date(), TushareConstants.TUSHARE_DATE_FORMAT);
		if (StringUtils.notNull(dateRange)) {
			String[] ranges = dateRange.split(",");
			begin = ranges[0];
			if (ranges.length == 2) {
				end = ranges[1];
			}
		}
		final String startDate = begin;
		final String endDate = end;
		Map<String, String> params = Maps.newHashMap();
		params.put("exchange", "SSE");
		params.put("start_date", startDate);
		params.put("end_date", endDate);
		consumeTushareData(TushareAPIs.TRADE_CAL, Fields.F_TRADE_CAL, DStockTradeCal.class, params, l -> {
			if (!l.isEmpty()) {
				tradeInfoMapper.deleteTradeCal(startDate, endDate);
				l.sort((Comparator<? super DStockTradeCal>) new Comparator<DStockTradeCal>() {

					public int compare(DStockTradeCal o1, DStockTradeCal o2) {
						return o1.getCalDate().compareTo(o2.getCalDate());
					}

				});
				dataStoreService.insertBatch(l);
				tradeInfoService.refreshTradeCal();
			}
		});
	}

	public void collectHistoryTradeDataDailyByDate(String date) {
		handleDataByDate(date, (d) -> consumeHistoryTradeDataDailyByDate(d));
	}

	public void collectHistoryTradeDataDailyByDateRange(String range) {
		collectTradeDataByDateRange(range, (d) -> consumeHistoryTradeDataDailyByDate(d));
	}

	private void consumeHistoryTradeDataDailyByDate(String tradeDate) {
		List<DStockTradeDaily> history = fetchTransData(TushareAPIs.TRADE_DAILY, DStockTradeDaily.class, Fields.F_DAILY, tradeDate);
		if (!history.isEmpty()) {
			tradeInfoMapper.deleteTradeDataDailyByDate(tradeDate);
			dataStoreService.insertBatch(history);
		}
	}

	public void collectHistoryTradeDataWeeklyByDate(String date) {
		handleDataByDate(date, (d) -> consumeHistoryTradeDataWeeklyByDate(d));
	}

	public void collectHistoryTradeDataWeeklyByDateRange(String range) {
		handleDataWeekByWeek(range, (d) -> consumeHistoryTradeDataWeeklyByDate(d));
	}

	private void consumeHistoryTradeDataWeeklyByDate(String tradeDate) {
		//获取当周最后一个交易日
		String td = tradeInfoService.queryRecentTradeDate(tradeDate);
		List<DStockTradeWeekly> history = fetchTransData(TushareAPIs.TRADE_WEEKLY, DStockTradeWeekly.class, Fields.F_WEEKLY, td);
		if (!history.isEmpty()) {
			tradeInfoMapper.deleteTradeDataWeeklyByDate(td);
			dataStoreService.insertBatch(history);
		}
	}

	public void collectHistoryTradeDataMonthlyByDate(String date) {
		handleDataByDate(date, (d) -> consumeHistoryTradeDataMonthlyByDate(d));
	}

	public void collectHistoryTradeDataMonthlyByDateRange(String range) {
		handleDataMonthByMonth(range, (d) -> consumeHistoryTradeDataMonthlyByDate(d));
	}

	private void consumeHistoryTradeDataMonthlyByDate(String tradeDate) {
		tradeDate = DateUtils.format(DateUtils.parseDate(DateUtils.firstDayOfMonth(DateUtils.parse(tradeDate, TushareConstants.TUSHARE_DATE_FORMAT))), TushareConstants.TUSHARE_DATE_FORMAT); //默认入参的月首日
		String lastTradeDateOfMonth = tradeInfoMapper.queryPreTradeDateByDate(tradeDate);
		List<DStockTradeMonthly> history = fetchTransData(TushareAPIs.TRADE_MONTHLY, DStockTradeMonthly.class, Fields.F_MONTHLY, lastTradeDateOfMonth);
		if (!history.isEmpty()) {
			tradeInfoMapper.deleteTradeDataMonthlyByDate(lastTradeDateOfMonth);
			dataStoreService.insertBatch(history);
		}
	}

	public void collectHistoryTradeDataDailyBasicByDate(String date) {
		handleDataByDate(date, (d) -> consumeHistoryTradeDataDailyBasicByDate(d));
	}

	public void collectHistoryTradeDataDailyBasicByDateRange(String range) {
		collectTradeDataByDateRange(range, (d) -> consumeHistoryTradeDataDailyBasicByDate(d));
	}

	private void consumeHistoryTradeDataDailyBasicByDate(String tradeDate) {
		List<DStockTradeDailyBasic> history = fetchTransData(TushareAPIs.TRADE_DAILY_BASIC, DStockTradeDailyBasic.class, Fields.F_DAILY_BASIC, tradeDate);
		if (!history.isEmpty()) {
			tradeInfoMapper.deleteTradeDataDailyBasicByDate(tradeDate);
			dataStoreService.insertBatch(history);
		}
	}

	public void collectHistoryTradeDataBlockTradeByDate(String date) {
		handleDataByDate(date, (d) -> consumeHistoryTradeDataBlockTradeByDate(d));
	}

	public void collectHistoryTradeDataBlockTradeByDateRange(String range) {
		collectTradeDataByDateRange(range, (d) -> consumeHistoryTradeDataBlockTradeByDate(d));
	}

	private void consumeHistoryTradeDataBlockTradeByDate(String tradeDate) {
		List<DStockBlockTrade> history = fetchTransData(TushareAPIs.TRADE_BLOCK_TRADE, DStockBlockTrade.class, Fields.F_BLOCK_TRADE, tradeDate);
		if (!history.isEmpty()) {
			tradeInfoMapper.deleteBlockTradeByDate(tradeDate);
			dataStoreService.insertBatch(history);
		}
	}

	private <T> List<T> fetchTransData(String api, Class<T> clazz, String fields, String tradeDate) {
		List<T> retList = Lists.newArrayList();
		if (tradeInfoService.isWeekend(tradeDate)) {
			return retList;
		}
		Map<String, String> params = Maps.newHashMap();
		params.put("trade_date", tradeDate);
		requestData(api, fields, clazz, params, retList);
		return retList;
	}

	public void collectHistoryTradeDataMoneyFlowByDate(String date) {
		handleDataByDate(date, (d) -> consumeHistoryTradeMoneyFlowByDate(d));

	}

	public void collectHistoryTradeDataMoneyFlowByDateRange(String range) {
		collectTradeDataByDateRange(range, (d) -> consumeHistoryTradeMoneyFlowByDate(d));

	}

	private void consumeHistoryTradeMoneyFlowByDate(String tradeDate) {
		List<DStockMoneyflow> history = fetchTransData(TushareAPIs.TRADE_MONEY_FLOW, DStockMoneyflow.class, Fields.F_MONEY_FLOW, tradeDate);
		if (!history.isEmpty()) {
			tradeInfoMapper.deleteTradeDataMoneyFlowByDate(tradeDate);
			dataStoreService.insertBatch(history);
		}
	}

	public void collectHistoryTradeDataMoneyFlowHsgtByDateRange(String range) {
		if (StringUtils.isNull(range)) {
			String today = DateUtils.format(new Date(), "yyyyMMdd");
			range = today + "," + today;
		}
		String[] days = range.split(",");
		Map<String, String> params = Maps.newHashMap();
		params.put("start_date", days[0]);
		params.put("end_date", days[1]);
		consumeTushareData(TushareAPIs.TRADE_MONEY_FLOW_HSGT, Fields.F_MONEY_FLOW_HSGT, DStockMoneyflowHsgt.class, params, l -> {
			if (!l.isEmpty()) {
				l.sort(new Comparator<DStockMoneyflowHsgt>() {

					public int compare(DStockMoneyflowHsgt o1, DStockMoneyflowHsgt o2) {
						return o1.getTradeDate().compareTo(o2.getTradeDate());
					}

				});
				tradeInfoMapper.deleteMoneyFlowHsgt(days[0], days[1]);
				dataStoreService.insertBatch(l);
			}
		});
	}

}
